package com.winter.admin.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundZSetOperations;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

/**
 * @author: zhangshuaiyin
 * @date: 2021/9/25 15:44
 */
@RestController
@RequestMapping("/rank")
public class RankController {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private static final String RANK_KEY = "rank";

    /**
     * 初始化数据
     */
    @GetMapping("/init")
    public void initData() {
        BoundZSetOperations zSetOps = redisTemplate.boundZSetOps(RANK_KEY);
        // 假设从数据库获取到去重之后的排行榜数据
        Set<DefaultTypedTuple> data = new HashSet<>();
        for (int i = 1; i < 500000; i++) {
            data.add(new DefaultTypedTuple<>("A" + i, (double) i));
        }
        zSetOps.add(data);
        data.clear();
        for (int i = 500000; i <= 1000000; i++) {
            data.add(new DefaultTypedTuple<String>("B" + i, (double) i));
        }
        zSetOps.add(data);
    }

    /**
     * 获取当前用户排名
     *
     * @param userCode 用户
     * @return 排名
     */
    @GetMapping("/getCurrentRank")
    public Long getCurrentRank(String userCode) {
        BoundZSetOperations zSetOps = redisTemplate.boundZSetOps(RANK_KEY);
        Long rank = zSetOps.reverseRank(userCode);
        return rank == null ? 0 : rank + 1;
    }

    /**
     * 更新用户分数
     *
     * @param userCode 用户
     * @param score 修改分数
     * @date 2021/8/31 13:42
     */
    @PostMapping("/updateScore")
    public void updateScore(String userCode, int score) {
        // 模拟存入数据库
        Random random = new Random();
        int i = random.nextInt(1000);
        BoundZSetOperations zSetOps = redisTemplate.boundZSetOps(RANK_KEY);
        // 当前分数, 分数.Integer.MAX_VALUE-数据库id 用于相同分数下排名;分数相同的用户，先获取到该分数的用户排名更高
        BigDecimal currentScore = new BigDecimal(score + "." + (Integer.MAX_VALUE - i));
        // 获取历史的分数
        Double scoreHistory = zSetOps.score(userCode);
        // 不存在该用户记录或者 历史分数比当前分数小,则更新缓存数据
        if (scoreHistory == null || BigDecimal.valueOf(scoreHistory).compareTo(currentScore) <= 0) {
            zSetOps.add(userCode, currentScore.doubleValue());
        }
    }

    /**
     * 查询前20名
     *
     * @return {@link Long}
     * @date 2021/8/31 11:58
     */
    @GetMapping("/listRank")
    public Set<Object> listRank() {
        BoundZSetOperations zSetOps = redisTemplate.boundZSetOps(RANK_KEY);
        return zSetOps.reverseRange(0, 19);
    }

    /**
     * 删除多余数据
     *
     * @return {@link Long}
     * @date 2021/8/31 13:41
     */
    @PostMapping("/removeData")
    public Long removeData() {
        BoundZSetOperations zSetOps = redisTemplate.boundZSetOps(RANK_KEY);
        return zSetOps.removeRange(0, 1000000);
    }


}
